/*
 * Copyright 2013 Sigurd Randoll <srandoll@digiway.de>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.digiway.rapidbreeze.server.model.storage;

import de.digiway.rapidbreeze.server.infrastructure.objectstorage.Column;
import de.digiway.rapidbreeze.server.infrastructure.objectstorage.Entity;
import de.digiway.rapidbreeze.server.infrastructure.objectstorage.Id;
import java.io.Serializable;
import java.net.URL;
import java.util.Objects;
import java.util.UUID;
import org.apache.commons.lang3.Validate;

/**
 * An instance of {@linkplain StorageProvider} represents a data provider in the
 * cloud where files can be downloaded from. Account data like username and
 * password can be specified which will be used to download from the Provider as
 * a premium member. Currently only Premium users a supported.
 *
 * @author Sigurd Randoll <srandoll@digiway.de>
 */
@Entity(table = "StorageProvider")
public class StorageProvider implements Serializable {

    @Id
    private String id;
    @Column
    private String storageProviderName;
    @Column
    private String clazz;
    @Column
    private String premiumUsername;
    @Column
    private String premiumPassword;
    private transient StorageProviderDownloadClient downloadClient;

    protected StorageProvider() {
        // req. by JPA
    }

    public StorageProvider(String name, String clazz) {
        Validate.notEmpty(name);
        Validate.notEmpty(clazz);
        this.storageProviderName = name;
        this.clazz = clazz;
        this.id = UUID.randomUUID().toString();
    }

    public void setPremiumPassword(String premiumPassword) {
        this.premiumPassword = premiumPassword;
    }

    public void setPremiumUsername(String premiumUsername) {
        this.premiumUsername = premiumUsername;
    }

    public String getPremiumPassword() {
        return premiumPassword;
    }

    public String getPremiumUsername() {
        return premiumUsername;
    }

    public boolean canHandle(URL url) {
        return createDownloadClient().canHandle(url);
    }

    public StorageProviderDownloadClient createDownloadClient() {
        if (downloadClient == null) {
            try {
                Class<?> cls = Class.forName(clazz);
                if (!StorageProviderDownloadClient.class.isAssignableFrom(cls)) {
                    throw new IllegalStateException("The configured class:" + clazz + " does not represent a valid " + StorageProviderDownloadClient.class.getSimpleName() + ".");
                }
                Class<StorageProviderDownloadClient> storageDownloadClass = (Class<StorageProviderDownloadClient>) cls;
                downloadClient = storageDownloadClass.newInstance();
            } catch (InstantiationException | IllegalAccessException | ClassNotFoundException ex) {
                throw new IllegalStateException("Cannot instantiate " + StorageProviderDownloadClient.class.getSimpleName() + " class:" + clazz, ex);
            }

        }
        if (!downloadClient.getAuthenticationStatus().equals(AuthenticationStatus.AUTHENTICATED) && premiumPassword != null && premiumUsername != null) {
            downloadClient.authenticate(premiumUsername, premiumPassword);
        }

        return downloadClient;
    }

    public String getName() {
        return storageProviderName;
    }

    @Override
    public String toString() {
        return "StorageProvider{" + "storageProviderName=" + storageProviderName + ", clazz=" + clazz + '}';
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 97 * hash + Objects.hashCode(this.id);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final StorageProvider other = (StorageProvider) obj;
        if (!Objects.equals(this.id, other.id)) {
            return false;
        }
        return true;
    }
}
